﻿using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using ICSharpCode.AvalonEdit;
using ICSharpCode.AvalonEdit.Editing;

namespace FFmpegVideoClip.Lib.UtilityControlsTools
{
    public class UserTextEditor: TextEditor
    {
        public static readonly Brush ErrorBrush = new SolidColorBrush(Colors.Red);

        public static readonly DependencyProperty DependencyTextProperty =
            DependencyProperty.Register("DependencyText", typeof(string), typeof(UserTextEditor), new PropertyMetadata(string.Empty, new PropertyChangedCallback((s, e) => 
            {
                if (s is UserTextEditor te && e.NewValue is string value)
                {
                    te.IsReadOnly = false;
                    te.Text = value;
                    te.IsReadOnly = true;
                }
            })));

        public static readonly DependencyProperty ParentControlBackgroundProperty =
           DependencyProperty.Register("ParentControlBackground", typeof(Brush), typeof(UserTextEditor), new PropertyMetadata(null,new PropertyChangedCallback((s, e) => 
           {
               UserTextEditor te = (UserTextEditor)s;
               if(te.Parent is Border control)
               {
                   if (e.NewValue is Brush value)
                       control.Background = value;
                   else if (string.IsNullOrEmpty(te.Text))
                   {
                       control.Background = ErrorBrush;
                   }
                   else control.Background = te.OldBackground;
               }
           })));

        public static readonly RoutedEvent OnEditorStateChangeEvent = EventManager.RegisterRoutedEvent("OnEditorStateChange", RoutingStrategy.Direct, typeof(RoutedEventHandler), typeof(UserTextEditor));


        private Brush? OldBackground;
        public Border? ParentControl => Parent as Border;

        public UserTextEditor() : this(new()) { }
        public UserTextEditor(TextArea textArea):base(textArea)
        {
            this.PreviewMouseDoubleClick += TextEditor_PreviewMouseDoubleClick;
            this.PreviewKeyDown += TextEditor_KeyDown;
            this.Loaded += UserTextEditor_Loaded;
            this.Unloaded += UserTextEditor_Unloaded;
            this.PreviewMouseRightButtonDown += UserTextEditor_PreviewMouseRightButtonDown;
            this.PreviewLostKeyboardFocus += UserTextEditor_PreviewLostKeyboardFocus;
        }

        private DependencyPropertyDescriptor? dpd;
        private void UserTextEditor_Loaded(object sender, RoutedEventArgs e)
        {
            if (dpd != null)
                return;
            dpd = DependencyPropertyDescriptor.FromProperty(IsReadOnlyProperty, typeof(TextEditor));
            dpd.AddValueChanged(this, OnRaiseEditorEvent);
            OldBackground = ParentControl?.Background;
            VerificationDocument();
        }


        private void UserTextEditor_Unloaded(object sender, RoutedEventArgs e)
        {
            if (dpd == null)
                return;
            dpd?.RemoveValueChanged(this, OnRaiseEditorEvent);
            dpd = null;
        }

        public void OnRaiseEditorEvent(object? sender, EventArgs e) => this.RaiseEvent(new(OnEditorStateChangeEvent, sender));

        public Brush ParentControlBackground
        {
            get { return (Brush)GetValue(ParentControlBackgroundProperty); }
            set { SetValue(ParentControlBackgroundProperty, value); }
        }

        public string DependencyText
        {
            get { return (string)GetValue(DependencyTextProperty); }
            set { SetValue(DependencyTextProperty, value);  }
        }

        public event RoutedEventHandler OnEditorStateChange
        {
            add { this.AddHandler(OnEditorStateChangeEvent, value);}
            remove { this.RemoveHandler(OnEditorStateChangeEvent, value); }
        }

        public bool DisableScroll { get => (bool)GetValue(DisableScrollProperty); set => SetValue(DisableScrollProperty, value); }
        public static readonly DependencyProperty DisableScrollProperty = DependencyProperty.Register("DisableScroll", typeof(bool), typeof(UserTextEditor), new PropertyMetadata(false, (s,e) => 
        {
            UserTextEditor ute = (UserTextEditor)s;
            if((bool)e.NewValue)
            {
                //ute.MouseWheel += DisableMouseWheel;
                ute.PreviewMouseWheel += DisableMouseWheel;
            }
            else
            {
                //ute.MouseWheel -= DisableMouseWheel;
                ute.PreviewMouseWheel -= DisableMouseWheel;
            }
        }));

        private static void DisableMouseWheel(object sender, MouseWheelEventArgs e)
        {
            if (!e.Handled)
            {
                e.Handled = true;
                if (((Control)sender).Parent is UIElement parent)
                    parent.RaiseEvent(new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta) { RoutedEvent = MouseWheelEvent, Source = sender });
            }
        }

        #region 附加属性 text例子

        //public static string GetAttachedText(DependencyObject obj)
        //{
        //    return (string)obj.GetValue(TextAttachedProperty);
        //}

        //public static void SetAttachedText(DependencyObject obj, string value)
        //{
        //    obj.SetValue(TextAttachedProperty, value);
        //}

        //// Using a DependencyProperty as the backing store for Text.  This enables animation, styling, binding, etc...
        //public static readonly DependencyProperty TextAttachedProperty =
        //    DependencyProperty.RegisterAttached("AttachedPropertyText", typeof(string), typeof(UserTextEditor), new PropertyMetadata(string.Empty, new PropertyChangedCallback((s, e) => { })));

        #endregion


        public void VerificationDocument()
        {
            if (string.IsNullOrEmpty(Text))
                ParentControl!.Background = ErrorBrush;
        }

        public void EnableEdit()
        {
            Keyboard.Focus(this);
            Focus();
            TextEditor_PreviewMouseDoubleClick(null!, null!);
        }

        private void TextEditor_PreviewMouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            if(this.IsReadOnly)
                this.IsReadOnly = false;
        }

        private void TextEditor_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
                UserTextEditor_PreviewLostKeyboardFocus(null!, null!);
        }
        private bool IsMouseRight = false;

        private void UserTextEditor_PreviewLostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
        {
            //System.Diagnostics.Debug.WriteLine("LostKeyboard");
            if (IsMouseRight)
            {
                IsMouseRight = false;
                e.Handled = true;
                return;
            }
            if (this.IsReadOnly)
                return;

            this.IsReadOnly = true;
        }

        private void UserTextEditor_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
        {
            IsMouseRight = true;
        }
    }
}
